<?php
/**
 * XmuSlh, web platform of Student Association Federation of Xiamen University
 * 
 * Rewritting one or some pages of StatusNet. 
 * To get the original version, please visit <http://status.net/>.
 * 
 * StatusNet, the distributed open-source microblogging tool
 * 
 * LICENCE: This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * Upload an avatar action.
 * Quite an old style one.
 * 
 * @author		ytukie <ytukie@gmail.com>
 * @version		0.1
 */

// XmuSlh only.
if ( !defined('XMUSLH')) { exit(1); }

// Requirements.
require_once INSTALLDIR . '/lib/slh_action.php';
require_once INSTALLDIR . '/lib/slh_util.php';

require_once INSTALLDIR . '/lib/slh_imagefile.php';

require_once INSTALLDIR . '/classes/Avatar.php';


class EditavatarAction extends Action
{
	/**
	 * Form mode.
	 */
	var $mode = null;
	
	/**
	 * Has some instruction?
	 */
	var $instruction = null;
	
	/**
	 * User.
	 */
	var $user = null;
	
	function title()
	{
		return '修改用户的头像!';
	}
	
	function prepare($args)
	{
		if ( !Rights::hasRight(slh_get_userrights(), RIGHT_ASSOCITION)) {
			return false;
		}
		
		parent::prepare($args);
		
		// Parameter from 'get' url
		$guser_id = $this->getTrimmedArg('guser_id');
		
		if ( !is_numeric($guser_id)) {
			return false;
		}
		
		// Check the source requiring this page
		$formtoken = $this->getTrimmedArg('formtoken');
		
		if (empty($formtoken)) {
			// Just 'get' the content.
			$this->user = User::staticGet('id', $guser_id);
			
			if (empty($this->user)) {
				$this->clientError('Cannot find the user.');
			}
		} else if ('uploadavatar' == $formtoken) {
			// upload post.
		}
		
		return true;
	}
	
	function handle($args)
	{
		parent::handle($args);
		
		if ($_SERVER['REQUEST_METHOD'] == 'POST') {
			$this->handlePost();
		} else {
			$this->showAction();
		}
	}
	
	/**
	 * Overrideing the showInnerContent().
	 */
	function showInnerContent()
	{
		$this->element('h3', null, '修改头像');
		
		$this->instruction('上传的头像文件需要满足什么要求?');
		
		$this->element('hr');
		$this->elementStart('div', 'cls_div_editavatar');
		
		$this->showInstruction();
		
		if ($this->mode == 'crop') {
			$this->showCropForm();
		} else {
			$this->showUploadForm();
		}
		
		$this->elementEnd('div');		
		$this->element('hr');
	}
	
	/**
	 * Add the jCrop stylesheet.
	 */
	function showStylesheets()
	{
		parent::showStylesheets();
		
		if ($this->mode == 'crop') {
			$this->cssLink('theme/base/css/jquery.Jcrop.css', 'base', 'screen, projection, tv');
			$this->cssLink('theme/base/css/action/editavatar.css');
		}
	}
	
	/**
	 * Add the jCrop scripts.
	 */
	function showScripts()
	{
		parent::showScripts();
		
		if ($this->mode == 'crop') {
			$this->script('jcrop/jquery.Jcrop.min.js');
			$this->script('action/editavatar.go.js');
		}
		
		$this->autofocus('avatarfile');
	}
	
// Overrided ends //////////////////////////////////////////////////////////////

	/**
	 * Shows the instruction of this page.
	 */
	function showInstruction()
	{
	if ($this->instruction) {
			$this->elementStart('div', array('class' => 'cls_div_instruction'));
			$this->instruction($this->instruction);
			$this->elementEnd('div');
		}
	}
	
	/**
	 * Shows the form with instruction.
	 */
	function showAction($instruction = null)
	{
		$this->instruction = $instruction;
		$this->showPage();
	}
	
	/**
	 * Handle a post requset: upload, crop, delete.
	 */
	function handlePost()
	{
		// Workaround for PHP returning empty $_POST and $_FILES when POST
		// length > post_max_size in php.ini
		if (empty($_FILES) &&
			empty($_POST) &&
			($_SERVER['CONTENT_LENGTH'] > 0)) {
			$msg = 'The server was unable to handle that mush POST data due to its current configuration.';
			$this->showAction($msg);
			return;
		}
		
		$this->checkSessionToken();
		
		if ($this->getTrimmedArg('upload')) {
			$this->uploadAvatar();
		} else if ($this->getTrimmedArg('crop')) {
			$this->cropAvatar();
		} else if ($this->getTrimmedArg('delete')) {
			$this->deleteAvatar();
		} else {
			$this->showAction('Unexpected form submission.');
		}
	}
	
	/**
	 * Show an uploading form.
	 */
	function showUploadForm()
	{
		// Get the user and profile. in the prepare()
		
		// Get the original(uploaded) avatar.
		$tinyAvatar = Avatar::getAvatarBySize($this->user->id, AVATAR_TINY_SIZE);
		$normalAvatar = Avatar::getAvatarBySize($this->user->id, AVATAR_NORMAL_SIZE);

		// Show the original ones.
		if ($tinyAvatar != false && $normalAvatar != false) {
			$this->elementStart('div', 'cls_div_avatarpreview');
			$this->element('dt', null, '原有头像信息');
			$this->elementStart('dd');
			$this->elementStart('ul');
				$this->elementStart('li');
				$this->element('h5', null, '正常:');
				$this->elementStart('div', array('class' => 'div_cls_normalavatar'));
				$this->element('img', array('src' => $normalAvatar->avatarurl()));
				$this->elementEnd('div');
				$this->elementEnd('li');
				
				$this->elementStart('li');
				$this->element('h5', null, '微型:');
				$this->elementStart('div', array('class' => 'div_cls_tinyavatar'));
				$this->element('img', array('src' => $tinyAvatar->avatarurl()));
				$this->elementEnd('div');
				$this->elementEnd('li');
			$this->elementEnd('ul');
			$this->elementEnd('dd');
			$this->elementEnd('div');
		}
		
		$this->elementStart('div', 'cls_div_uploadavatar');
		$this->elementStart('form', array('enctype'	=> 'multipart/form-data',
										  'method'	=> 'post',
										  'id'		=> 'id_form_uploadavatar',
										  'class'	=> 'cls_form',
										  'action'	=> slh_action2url('editavatar', array('guser_id' => $this->user->id))));
		
		$this->elementStart('fieldset');
		$this->element('legend', null, 'upload avatar');
		$this->hidden('token', slh_session_token());
		
		$this->elementStart('dl', array('class' => 'cls_dl_form'));
		$this->element('dt', null, '上传/删除头像');
		$this->elementStart('dd');
		
		$this->elementStart('ul');
			$this->hidden('MAX_FILE_SIZE',
							   ImageFile::maxAvatarSizeInt());
			
			$this->elementStart('li');
			$this->element('label', array('for' => 'avatarfile'), '上传头像!');
			$this->element('input', array('id' => 'avatarfile',
										  'name' => 'avatarfile',
										  'type' => 'file'));
			$this->inputtips('图片大小限制为:' . ImageFile::maxAvatarSize());
			$this->elementEnd('li');
		$this->elementEnd('ul');
		$this->elementEnd('dd');
		$this->elementEnd('dl');
		
		$this->elementStart('div', 'formaction');
		$this->submit('upload', '上传图片');
		$this->submit('delete', '删除头像');
		$this->element('a', array('href' => slh_action2url('editassociationuser',
								  	   					   array('guser_id' => $this->user->id)),
								  'title' => '返回编辑用户.'),
								  '返回...');
		$this->elementEnd('div');
		
		$this->elementEnd('fieldset');
		$this->elementEnd('form');
		$this->elementEnd('div');
	}
	
	/**
	 * Show a cropping form.
	 */
	function showCropForm()
	{
		$this->elementStart('form', array('method'	=> 'post',
										  'id'		=> 'form_settings_avatar',
										  'class'	=> 'form_settings',
										   'action'	=> slh_action2url('editavatar', array('guser_id' => $this->user->id))));
		
		$this->elementStart('fieldset');
		$this->element('legend', null, 'crop avatar');
		$this->hidden('token', slh_session_token());
		foreach (array('avatar_crop_x', 'avatar_crop_y', 'avatar_crop_w', 'avatar_crop_h') as $crop_info) {
			$this->element('input', array('name' => $crop_info,
										  'type' => 'hidden',
										  'id'   => $crop_info));
		}
		
		$this->elementStart('dl', array('class' => 'cls_dl_form'));
		$this->element('dt', null, '剪裁头像');
		$this->elementStart('dd');
		
		$this->elementStart('ul');
			$this->elementStart('li');
			$this->element('h5', null, '剪裁之前:');
			$this->elementStart('div', array('id'	=> 'avatar_original'));
			$this->element('img', array('src'	=> Avatar::url($this->filedata['filename']),
										'width'	=> $this->filedata['width'],
										'height'=> $this->filedata['height'],
										'alt'	=> $this->filedata['filename']));
			$this->elementEnd('div');
			$this->elementEnd('li');
			
			$this->elementStart('li');
			$this->element('h5', null, '剪裁之后:');
			$this->elementStart('div', array('id'	=> 'avatar_preview'));
			$this->element('img', array('src'	=> Avatar::url($this->filedata['filename']),
										'width'	=> AVATAR_LARGE_SIZE,
										'height'=> AVATAR_LARGE_SIZE,
										'alt'	=> $this->filedata['filename']));
			$this->elementEnd('div');
			$this->elementEnd('li');

		$this->elementEnd('ul');
		$this->elementEnd('dd');
		$this->elementEnd('dl');
		
		$this->elementStart('div', 'formaction');
		$this->submit('crop', '剪裁');
		$this->elementEnd('div');
		
		$this->elementEnd('fieldset');
		$this->elementEnd('form');
		
	}
	
	/**
	 * Handle an image upload.
	 * 
	 * Does all the magic for handling an image upload, and crops the 
	 * image by default.
	 */
	function uploadAvatar()
	{
		try {
			$imagefile = ImageFile::fromUpload('avatarfile');
		} catch (Exception $e) {
			$this->showAction($e->getMessage());
			return;
		}
		
		if (null === $imagefile) {
			$this->showAction('No file uploaded.');
			return;
		}
		
		$mimetype = $imagefile->preferredType();
		$filename = Avatar::filename($this->user->id,
									 image_type_to_extension($mimetype),
									 null,
									 'tmp' . uniqid());
		$filepath = Avatar::path($filename);
		
		$imagefile->copyTo($filepath);
		
		$filedata = array('filename' => $filename,
						  'filepath' => $filepath,
						  'width'	 => $imagefile->width,
						  'height'	 => $imagefile->height,
						  'mimetype' => $mimetype);
		
		$_SESSION['FILEDATA'] = $filedata;
		$this->filedata = $filedata;
		
		$this->mode = 'crop';
		
		$this->showAction('选择一个图像范围作为最终的头像.');
	}
	
	/**
	 * Handle the results of jcrop.
	 * 
	 * TODO: A little max.
	 */
	function cropAvatar()
	{
		if ( !isset($_SESSION['FILEDATA'])) {
			$this->showAction('No image to crop. Please upload again.');
			return;	
		}
		
		$filedata = $_SESSION['FILEDATA'];
		
		if ( !$filedata) {
			$this->serverError('Lost our file data.');
			return;
		}
		
		$file_d = ($filedata['width'] > $filedata['height']) ? $filedata['height'] : $filedata['width'];
		
		$dest_x = $this->getArg('avatar_crop_x') ? $this->getArg('avatar_crop_x') : 0;
		$dest_y = $this->getArg('avatar_crop_y') ? $this->getArg('avatar_crop_y') : 0;
		$dest_w = $this->getArg('avatar_crop_w') ? $this->getArg('avatar_crop_w') : $file_d;
		$dest_h = $this->getArg('avatar_crop_h') ? $this->getArg('avatar_crop_h') : $file_d;
		// Autofit the square.
		// $size = min($dest_w, $dest_h);

		// Delete the original data in the database.
		$avatar = new Avatar();
		$avatar->user_id = $this->user->id;
		if ($avatar->find()) {
			while ($avatar->fetch()) {
				if ($avatar->delete()) {
					@unlink($avatar->avatarpath());
				}
			}
		}
		
		// Get the normal and tiny sizes' avatar file, actually exists in the filesystem. 
		// Insert the two avatars.
		foreach (array(AVATAR_NORMAL_SIZE, AVATAR_TINY_SIZE) as $size) {
			// Original size = normal size.
			$imagefile = new ImageFile($this->user->id, $filedata['filepath']);
			$filename = $imagefile->avatarResize($size, $size, $dest_x, $dest_y, $dest_w, $dest_h);
			
			$avatar = new Avatar();
			$avatar->user_id = $this->user->id;
			$avatar->size = $size;
			$avatar->mimetype = $imagefile->mimetype;
			$avatar->avatarname = $filename;
			
			if ( !$avatar->insert()) {
				// Logs?
				$this->serverError('Saving cropped avatar error.');
			}
		}

		// Delete the original file.
		@unlink($filedata['filepath']);
		unset($_SESSION['FILEDATA']);
		$this->mode = 'finished';
		
		$this->unsetSessionToken();
		// $this->showAction('Avatar updated.');
		
		slh_redirect(slh_action2url('editassociationuser', array('guser_id' => $this->user->id)), 303);
	}
	
	/**
	 * Handle the deletion of the avatars.
	 */
	function deleteAvatar()
	{
		// Delete the original data in the database.
		$avatar = new Avatar();
		$avatar->user_id = $this->user->id;
		if ($avatar->find()) {
			while ($avatar->fetch()) {
				if ($avatar->delete()) {
					@unlink($avatar->avatarpath());
				}
			}
		}
		
		slh_redirect(slh_action2url('editassociationuser', array('guser_id' => $this->user->id)), 303);
	}
}

?>